import IEntitySystem from "../../base/ECSR/IEntitySystem";
import GameClientData from "../data/GameClientData";
import Guid from "common/utils/Guid";
import AimComponent from "../components/AimComponent";
import BubbleUtil from "../BubbleUtil";
import BubbleComponent from "../components/BubbleComponent";
import TransformComponent from "scripts/base/ECSR/components/TransformComponent";
import MapComponent from "../components/MapComponent";
import AimPathComponent from "../components/AimPathComponent";

export default class FindPathSystem extends IEntitySystem
{
    path:cc.Vec2[] = [];
    aimVec:cc.Vec2 = cc.Vec2.ZERO;

    aimPathCom:AimPathComponent = null;
    constructor(world)
    {
        super(world);
        this.aimPathCom = new AimPathComponent();
    }

    // 每逻辑帧调用
    Execute()
    {
        if(GameClientData.selfControlEntityId === "")
        {
            return;
        }
        let bubbleEntity = this.world.AddEntity(GameClientData.selfControlEntityId);

        let aimComponent = bubbleEntity.GetComponent("AimComponent") as AimComponent;
        if(aimComponent.enable)
        {
            if(!this.aimVec.equals(aimComponent.aimVec))
            {
                this.aimVec = aimComponent.aimVec;
                this.FindPath(this.aimVec);
                this.aimPathCom.path = this.path;
                this.aimPathCom.isUpdate = true;
                bubbleEntity.AddComponent(this.aimPathCom);
            }
        }
        else
        {
            bubbleEntity.RemoveComponent(this.aimPathCom);
        }
    }

    FindPath(aimVec:cc.Vec2)
    {
        let mapEntity = this.world.GetEntity(GameClientData.mapId);
        let mapCom = mapEntity.GetComponent("MapComponent") as MapComponent;

        let tmpNormalizeVec = cc.v2(aimVec);
        let currPos = AimComponent.aimPoint.sub(mapCom.position); // 转换到地图坐标系
        this.path = [];
        this.path.push(currPos.add(mapCom.position));    // 转换到世界坐标系
        let stepLen = 65.4 * 0.5;
        let leftBorderline = -360 + 32.7;
        let rightBorderline = 360 - 32.7;

        this.aimPathCom.isFind = false;

        for(let i = 0; i < 50; ++i)
        {
            let nowX = 0;
            let nowY = 0;
            let deltaX = stepLen * tmpNormalizeVec.x;
            let deltaY = stepLen * tmpNormalizeVec.y;
            if(deltaX + currPos.x >= rightBorderline)
            {
                nowX = rightBorderline;
                nowY = (rightBorderline - currPos.x) / tmpNormalizeVec.x * tmpNormalizeVec.y + currPos.y;
            }
            else if(deltaX + currPos.x <= leftBorderline)
            {
                nowX = leftBorderline;
                nowY = Math.abs((leftBorderline - currPos.x) / tmpNormalizeVec.x) * tmpNormalizeVec.y + currPos.y;
            }
            else
            {
                nowX = deltaX + currPos.x;
                nowY = deltaY + currPos.y;
            }


            currPos.x = nowX;
            currPos.y = nowY;

            let rowAndCol = BubbleUtil.getRowAndColByPos(nowX, nowY, mapCom.bubbleMap.length);

            if(BubbleUtil.checkPointValid(nowX, nowY, rowAndCol.x, rowAndCol.y, mapCom.bubbleMap.length))
            {
                cc.log("findPath|---------2------ checkPointValid True|i = " + i + "rowAndCol=" + rowAndCol.toString());

                let result = this.IsCollision(mapCom.bubbleMap, rowAndCol.x, rowAndCol.y, currPos);
                if(result)
                {
                    cc.log("findPath|collision, rowAndCol=" + rowAndCol.toString());
                    this.aimPathCom.isFind = true;
                    let mapTargetPos = BubbleUtil.getPosByRowAndCol(rowAndCol.x, rowAndCol.y, mapCom.bubbleMap.length);
                    this.aimPathCom.targetPos = mapTargetPos.add(mapCom.position);
                    break;
                }
            }

            if(currPos.x + 32.7 >= 360)
            {
                this.path.push(cc.v2(currPos.add(mapCom.position)));
                tmpNormalizeVec.x *= -1;
            }
            if(currPos.x - 32.7 <= -360)
            {
                tmpNormalizeVec.x *= -1;
                this.path.push(cc.v2(currPos.add(mapCom.position)));
            }
        }
        this.path.push(cc.v2(currPos.add(mapCom.position)));
        cc.log("findPath|path node size " + this.path.length);
        cc.log("findPath|path[0]" + this.path[0].toString());
    }

        /**
     * bubble ball在调整位置后可能有碰撞，但是在原始路径上可能还没有相撞
     * @param bubbleMap 
     * @param row 
     * @param col 
     */
    IsCollision(bubbleMap:string[][], row, col, realPos:cc.Vec2): boolean
    {
        if(row < 0 || row > bubbleMap.length || col < 0 || col > (row+1) % 2 + 10)
        {
            return false;
        }
        // 调整的位置不能有ball
        if(row < bubbleMap.length && bubbleMap[row][col] !== null) return false;

        let offsetCol = row % 2 == 0 ? col  -1: col;

        let transCom:TransformComponent = null;

        if(row - 1 >= 0)
        {
            if(offsetCol < bubbleMap[row-1].length && bubbleMap[row-1][offsetCol] != null)
            {
                transCom = this.world.GetComponentByEntityId(bubbleMap[row-1][offsetCol], "TransformComponent") as TransformComponent;
                if(BubbleUtil.isCollisionRaw(transCom.GetPosition(), realPos)) return true;
            }
            if(offsetCol + 1 < bubbleMap[row-1].length && bubbleMap[row-1][offsetCol+1] != null)
            {
                transCom = this.world.GetComponentByEntityId(bubbleMap[row-1][offsetCol+1], "TransformComponent") as TransformComponent;
                if(BubbleUtil.isCollisionRaw(transCom.GetPosition(), realPos)) return true;
            }
        }

        if(row < bubbleMap.length)
        {
            if(col -1 >= 0 && bubbleMap[row][col-1] != null)
            {
                transCom = this.world.GetComponentByEntityId(bubbleMap[row][col-1], "TransformComponent") as TransformComponent;
                if(BubbleUtil.isCollisionRaw(transCom.GetPosition(), realPos)) return true;
            }
            if(col + 1 < bubbleMap[row].length && bubbleMap[row][col+1] != null)
            {
                transCom = this.world.GetComponentByEntityId(bubbleMap[row][col+1], "TransformComponent") as TransformComponent;
                if(BubbleUtil.isCollisionRaw(transCom.GetPosition(), realPos)) return true;
            }
        }

        if(row + 1 < bubbleMap.length)
        { 
            if(offsetCol < bubbleMap[row+1].length && bubbleMap[row+1][offsetCol] != null)
            {
                transCom = this.world.GetComponentByEntityId(bubbleMap[row+1][offsetCol], "TransformComponent") as TransformComponent;
                if(BubbleUtil.isCollisionRaw(transCom.GetPosition(), realPos)) return true;
            }
            if(offsetCol + 1 < bubbleMap[row].length && bubbleMap[row+1][offsetCol+1] != null)
            {
                transCom = this.world.GetComponentByEntityId(bubbleMap[row+1][offsetCol+1], "TransformComponent") as TransformComponent;
                if(BubbleUtil.isCollisionRaw(transCom.GetPosition(), realPos)) return true;
            }
        }

        return false;
    }
}